home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / GNUUCP_2 / SOURCE / SYSDEP.MSD < prev    next >
Text File  |  1989-07-31  |  14KB  |  657 lines

  1. /*
  2.  * @(#)sysdep.msdos 1.6 87/09/23    Copyright 1987 Free Software Foundation, Inc.
  3.  *
  4.  * Copying and use of this program are controlled by the terms of the
  5.  * GNU Emacs General Public License.
  6.  */
  7.  
  8. #ifndef lint
  9. char sysdep_version[] = "@(#)sysdep.msdos gnuucp Version hoptoad-1.6";
  10. #endif
  11.  
  12. /* Microsoft DOS */
  13. #include "includes.h"
  14. #include "uucp.h"
  15. #include "sysdep.h"
  16.  
  17. /* Structure for find first/next (find()).
  18.  * NOTE: the DPB pointer is a double word 
  19.  * character pointer; here it is declared as a
  20.  * long, to avoid problems with the various
  21.  * size of char *'s.
  22.  */
  23.  
  24. struct _xfbuf {
  25.     char s_attrib;          /* Search attribute */
  26.  
  27.     /* These do not need to be initialized */
  28.     char drive;             /* 0 == current, 1 == A: ... */
  29.     char fcbname[11];       /* FCB name, */
  30.     unsigned ent;
  31.     long dpb_ptr;
  32.     unsigned dirstart;
  33.  
  34.     /* These are returned by DOS */
  35.     char f_attrib;          /* found attribute, */
  36.     unsigned time;          /* Packed time, */
  37.     unsigned date;          /* Packed date */
  38.     long fsize;             /* file size, */
  39.     char name[13];          /* found name */
  40. };
  41.  
  42. #define GET_TIME 0x2c   /* DOS function number for get_time */
  43. #define DOS_INT  0x21   /* DOS interrupt number */
  44.  
  45. typedef struct timetype {
  46.     unsigned hour;
  47.     unsigned minute;
  48.     unsigned sec;
  49.     unsigned hsec;
  50. } TIME, *TIME_PTR;
  51.  
  52.  
  53. /*
  54.  * Note that NAMESIZE should be the max length of a file name, including
  55.  * all its directories, drive specifiers, extensions, and the like.
  56.  * E.g. on a Unix with 14-char file names, NAMESIZE is several hundred
  57.  * characters, since the 14-char names can be nested.
  58.  */
  59. /* FIXME, these should all be uppercase. */
  60. /* FIXME, these are duplicated from includes.h */
  61. #define    FNAMESIZE    sizeof("FILENAME")    /* 8 chars */ 
  62. #define    NAMESIZE    128        /* full path size */ 
  63. #define    UFNAMESIZE      5               /* uux id size */ 
  64.  
  65.  
  66. /* Our variables */
  67.  
  68. char    hayesinit[] = "\r\r\rATZX1S0=1\r";
  69.  
  70. int    fdtty;                /* File descriptor for tty line */
  71.  
  72. void sigint();                /* Forward declaration */
  73.  
  74. /*
  75.  * Translation between integer baud rates and Unix baud rates (grumble)
  76.  */
  77. static struct baudtab {
  78.     int    baudrate, damn_B_code;
  79. } baudtab[] = {
  80.     50,    B50,
  81.     75,    B75,
  82.     110,    B110,
  83.     134,    B134,
  84.     150,    B150,
  85.     200,    B200,
  86.     300,    B300,
  87.     600,    B600,
  88.     1200,    B1200,
  89.     1800,    B1800,
  90.     2400,    B2400,
  91.     4800,    B4800,
  92.     9600,    B9600,
  93.     19200,    B19200,
  94.     38400,    B38400,
  95. };
  96.  
  97. static int
  98. damn_B(baud)
  99. {
  100.     register struct baudtab *b;
  101.  
  102.     for (b = baudtab; b->baudrate < baud; b++) continue;
  103.     if (b->baudrate == baud)
  104.         return b->damn_B_code;
  105.     return EXTB;    /* Maybe this'll get clocking from the modem */
  106. }
  107.  
  108. /*
  109.  * Open the serial line for an incoming call.
  110.  * Argument of NULL or empty string means stdin.
  111.  */
  112. int
  113. openline(ttynam, baud)
  114.     char    *ttynam;
  115.     int    baud;
  116. {
  117.     int ontheline = !(ttynam && ttynam[0]);    /* FIXME, this is garbage */
  118.  
  119. #ifndef COMPORT
  120.     if ((fdtty = open(ttynam, O_RDWR)) < 0)
  121.     {
  122.         printf("Cannot open %s for read/write %d\n",
  123.             ttynam, errno);
  124.         exit(1);
  125.     }
  126. #else
  127.     set_tty(COMM1, damn_B(baud), CS8, MENBL);
  128.     printf("uucico : initializing modem.\n");
  129.     xwrite(hayesinit, sizeof(hayesinit)-1);
  130.  
  131.     printf("uucico : waiting for call\n");
  132.     while ((get_msr() & CD) == 0) {
  133.         if (kbhit() != 0) {
  134.             printf("uucico : aborting at user's request.");
  135.             set_tty(0,0,0,MDSBL);   /* Hang up */
  136.             sleep(2);
  137.             reset_tty();
  138.             exit(1);
  139.          }
  140.     }
  141.     printf("uucico : inbound call detected\n");
  142.     init_comm();
  143.     inp_flush();
  144.     sleep(2);
  145. #endif
  146.     signal(SIGINT,sigint);
  147.     return SUCCESS;
  148. }
  149.  
  150. /*
  151.  * openout() -- open line for dialout
  152.  */
  153. int
  154. openout(ttynam, baud)
  155.     char    *ttynam;
  156.     int    baud;
  157. {
  158.  
  159. #ifdef COMPORT
  160.     set_tty(COMM1, damn_B(baud), CS8, MENBL);
  161.     DEBUG(2,"initializing modem.\n", 0);
  162.     xwrite(hayesinit, sizeof(hayesinit)-1);
  163.     init_comm();
  164.     inp_flush();
  165.     sleep(2);
  166. #else
  167.     if ((fdtty = open(ttynam, O_RDWR)) < 0)
  168.     {
  169.         if (debug > 0) {
  170.             printf("Cannot open %s for read/write %d\n",
  171.                 ttynam, errno);
  172.         }
  173.         exit(1);
  174.     }
  175.     FIXME, do stty() here.
  176. #endif
  177.     signal(SIGINT,sigint);
  178.     return SUCCESS;
  179. }
  180.  
  181. /*
  182.  * Basement level I/O routines
  183.  *
  184.  * xwrite() writes a character string to the serial port
  185.  * xgetc() returns a character from the serial port, or an EOF for timeout.
  186.  * sigint() restores the state of the serial port on exit.
  187.  * hangup() hangs up the 'fone (e.g. drops DTR).
  188.  */
  189.  
  190. void
  191. sigint()
  192. {
  193.     /* Restore terminal settings on dialout line */
  194.     hangup();
  195.     exit(0);
  196. }
  197.  
  198. xwrite(buf,ctr)
  199.     char *buf;
  200.     int ctr;
  201. {
  202.     int i;
  203.  
  204. #ifndef COMPORT
  205.     return write(fdtty,buf,ctr);
  206. #else
  207.     for (i=0;i<=ctr;i++) {
  208.         outp_char(buf[i]);
  209.     }
  210.     return ctr;
  211. #endif
  212. }
  213.  
  214.  
  215.  
  216. /*
  217.  * Serial port reading routine
  218.  */
  219. int
  220. xgetc()
  221. {
  222.     char data;
  223.  
  224. #ifndef COMPORT
  225.     /* Warning: No timeouts... */
  226.     read(fdtty,&data,1);
  227.     return(data & 0xFF);
  228. #else
  229.     int i;
  230.     unsigned s;
  231.     TIME n;
  232.  
  233.     i = 0;
  234.     get_time(&n);
  235.     s = n.sec;
  236.  
  237.     /*
  238.      * Implement timeouts by staring at the clock while we wait.
  239.      * When the second hand moves, bump our counter.  This is a lot
  240.      * easier than figuring out the time when we'd time out (in hours,
  241.      * minutes, and seconds!) and comparing against that, which is
  242.      * what people tend to do in Unix where the time is just an integer
  243.      * number of seconds.
  244.      */
  245.     while (i < BYTE_TIMEOUT) {
  246.         while (s == n.sec) {
  247.             if(inp_cnt() != 0) {
  248.                 data = inp_char();
  249.                 return (data & 0xFF);
  250.             }
  251.             get_time (&n);
  252.         }
  253.         s = n.sec;
  254.         ++i;
  255.     }
  256.     return(EOF);
  257. #endif
  258. }
  259.  
  260. /*
  261.  * Hang up the 'fone.
  262.  */
  263. int
  264. hangup()
  265. {
  266.     /* Restore terminal settings on dialout line */
  267.     static char    a[] = "+++",
  268.             o[] = "OK",
  269.             h[] = "ATH0\r";
  270.     int         retry = 5;
  271.  
  272.     while (instr(o, strlen(o)) && retry--)
  273.         xwrite(a, strlen(a)-1);
  274.  
  275.     xwrite(h, strlen(h)-1);
  276.     if (instr(o, strlen(o)) || !retry)
  277.         DEBUG(0, "uucico: problem hanging up\n", 0);
  278.  
  279. #ifndef COMPORT
  280.         close(fdtty);
  281. #else
  282.     set_tty(0,0,0,MDSBL);   /* Hang up like a nice programme */
  283.         reset_tty();        /* Pop the serial port's pram off */
  284.         uninit_comm();        /* Uninit the interrupt */
  285. #endif
  286.     sleep(3);        /* Wait with DTR down */
  287.     exit(0);
  288. }
  289.  
  290. /* CP/M and MSDOS and ST need these routines.  Probably should use
  291.  * the new names, but for now...
  292.  */
  293. bzero(s, cnt)
  294. register char    *s;
  295. register int    cnt;
  296. {
  297.     register int    i;
  298.     for (i = 0; i < cnt; i++) {
  299.         *s++ = '\0';
  300.     }
  301. }
  302.  
  303. bcopy(from, to, cnt)
  304. register char    *from;
  305. register char    *to;
  306. register int    cnt;
  307. {
  308.     register int    i;
  309.     for (i = 0; i < cnt; i++) {
  310.         *to++ = *from++;
  311.     }
  312. }
  313.  
  314. /*
  315.  * Function to clean up all the loose ends if the user wishes to
  316.  * abort UUSLAVE
  317.  */
  318. int handler()
  319. {
  320.  
  321.     printf("\nAborting UUSLAVE\n");
  322. #ifdef COMPORT
  323.     set_tty(0,0,0,MDSBL);    /* drop DTR to hang up */
  324.     sleep(2);                     /* let it settle */
  325.     reset_tty();                  /* put the port back in condition it
  326.                       was before running the programme */
  327. #endif
  328.     exit(1);                      /* AWWAAAYY! */
  329. }
  330.  
  331. #ifdef COMPORT
  332. /*
  333.  * MSDOS routines for handling the comm port.
  334.  *
  335.  * get_time(n)
  336.  * TIME_PTR n;
  337.  *
  338.  * fills timetype structure n with current time using DOS interrupt 21
  339.  *
  340.  */
  341.  
  342. get_time(n)
  343. TIME_PTR n;
  344. {
  345.   union REGS inregs;
  346.   union REGS outregs;
  347.  
  348.   inregs.h.ah = GET_TIME;
  349.  
  350.   int86(DOS_INT, &inregs, &outregs);
  351.  
  352.   n->hour = outregs.h.ch;
  353.   n->minute  = outregs.h.cl;
  354.   n->sec  = outregs.h.dh;
  355.   n->hsec = outregs.h.dl;
  356.  
  357.   return(0);
  358. }
  359.  
  360. sleep(x)
  361. int x;
  362. {
  363.   int i;
  364.   unsigned s;
  365.   TIME n;               /* current time record */
  366.  
  367.   i = 0;
  368.   get_time(&n);
  369.   s = n.sec;
  370.  
  371.   while (i < x){
  372.     while (s == n.sec)
  373.       get_time(&n);
  374.     s = n.sec;
  375.     ++i;
  376.   }
  377. }
  378. #endif
  379.  
  380.  
  381.  
  382.  
  383. /*
  384.  * Returns 1 if a matching file was found, 0 if not.
  385.  */
  386. find(pathname,flag,pxfbuf)
  387.     char *pathname;
  388.     int flag;
  389.     struct _xfbuf *pxfbuf;
  390. {
  391.     union REGS inregs, outregs;
  392.  
  393.     inregs.x.dx = (unsigned int) pxfbuf;
  394.     inregs.h.ah = 26;
  395.     intdos(&inregs,&outregs);       /* set up DTA */
  396.  
  397.     inregs.x.dx = (unsigned int) pathname;
  398.     inregs.x.cx = 22;               /* the search atribute */
  399.     if (flag == 0) 
  400.           inregs.h.ah = 78;       /* if this is the first time FIND FIRST */
  401.     else {
  402.           inregs.h.ah = 79;       /* if this is not the first time FIND NEXT */
  403.           flag = 1;
  404.     }
  405.  
  406.     intdos(&inregs,&outregs);
  407.  
  408.     if ((outregs.x.ax == 18) || (outregs.x.ax == 3))
  409.           return (0);
  410.  
  411.     return(1);
  412.  
  413. }
  414.  
  415. /*
  416.  * Create a temporary file name for receiving a file into.
  417.  * "name" is the name we will actually eventually want to use for the file.
  418.  * We currently ignore it, but some OS's that can't move files around
  419.  * easily might want to e.g. put the temp file into the same directory
  420.  * that this file is going into.
  421.  *
  422.  * FIXME:
  423.  * This interface should be able to return a "possible" filename, and
  424.  * be re-called if the name is already in use, to get another.
  425.  * This avoids checking here whether the name is good -- saving system calls.
  426.  */
  427. char *
  428. temp_filename(name)
  429.     register char *name;
  430. {
  431.     static char tname[NAMESIZE];
  432.     char *t;
  433.     if ((t = tmpnam(NULL)) != NULL  && !curtemp)
  434.         bcopy(t,tname,strlen(t));
  435.     else
  436.         sprintf(tname,"%s/%s/uutemp.$$$", spool_path, host_name);
  437.     DEBUG(2,"Using temp file %s\n", tname);
  438.     return tname;
  439. }
  440.  
  441.  
  442. /*
  443.  * Transform a filename from Unix format into a local
  444.  * filename that will work in the local file system.
  445.  *
  446.  * E.g. LCK..hoptoad --> hoptoad\.LCK
  447.  *    C.hoptoadA1234 --> hoptoad\A1234.C
  448.  * etc.
  449.  * FIXME:  this is not done for anything but C. and D. files currently.
  450.  *         It does NOT work for LCK. and STST. files!
  451.  */
  452. char *
  453. munge_filename(name)
  454.     register char *name;
  455. {
  456.     register char *p;
  457.  
  458.     static char buffer[NAMESIZE+SLOP];
  459.     char mname[MAX_HOST];        /* master's name */
  460.     char cwdir[NAMESIZE];        /* current working director */
  461.     char ufname[UFNAMESIZE + 1];    /* distinctive 5 char UU file ID */
  462.     int i;                /* counter */
  463.  
  464. /* FIXME there is a problem when host names are shorter than six chars */
  465. /* ok, fixed, gmp (see also getname() ) */
  466.  
  467.     DEBUG(4,"Munge_filename  input: %s\n", name);
  468.  
  469.     if (name[0] == '/' || name[0] == '~' || name[1] != '.') {
  470.         /* Don't munge things that start with / or ~, or which
  471.          * aren't uucp internal file names with 2nd char dot */
  472. #ifdef NOTDEF
  473. /* This bit of code was in local_send_file.  I'm not sure why.
  474.  * If it belongs anywhere, it belongs here, but I don't see why it exists.
  475.  * If it's going to stay here, it needs a bit of conversion.
  476.  */
  477.     if (strstr(srcnam, "/\\"))
  478.         strcpy (temp, srcnam);     /* if already contains path info */
  479.     else {
  480.         strcpy (temp, host_name);
  481.         strcat (temp, "\\");
  482.         strcat (temp, srcnam);  /* otherwise ref to hosts' subdir */
  483.     }
  484. #endif
  485.         p = name;
  486.     } else {
  487.         /*
  488.          * This is a uucp-internal C., D., or other name.
  489.          * Munge the hell out of it.  For MSDOS, we can't
  490.          * handle the 14-character names of Unix, so change
  491.          * it to:
  492.          * 
  493.          * L.hostGNNNN  -> host/GNNNN.L
  494.          */
  495.         bzero(cwdir, sizeof cwdir);
  496.         bzero(ufname, sizeof ufname);
  497.  
  498.         i = strlen(name);
  499.         strncpy(mname, &name[2], i - (2 + UFNAMESIZE));
  500.         mname[i - (2 + UFNAMESIZE)] = '\0';
  501.  
  502.         strcpy(buffer, spool_path);
  503.         strcat(buffer, "/");
  504.         strcat(buffer, mname);    /* get host's directory name */
  505.  
  506.         /*
  507.          * Quick (?) test to see if we already have a directory
  508.          * for this host.
  509.          */
  510.         getcwd(cwdir,NAMESIZE);        /* save current directory */
  511.         if (chdir(buffer) == -1) {    /* If new dir doesn't exist, */
  512.             if (mkdir(buffer) == -1) {    /* ... make one */
  513.                 DEBUG(0, "Can't make new directory %s\n", buffer);
  514.             } else {
  515.                 DEBUG(4, "Making new directory %s\n", buffer);
  516.             }
  517.         } else
  518.             chdir(cwdir);    /* pop back to the home directory */
  519.         
  520.         /* build actual file name */
  521.         p = buffer + strlen(buffer);
  522.         for(i = 0; i <= UFNAMESIZE; i++)
  523.             ufname[UFNAMESIZE - i] = name[strlen(name) - i];
  524.  
  525.         *p++ = '/';
  526.         strncpy(p, &name[i - UFNAMESIZE], UFNAMESIZE);    /* GNNNN */
  527.         strcat(p, ".");
  528.         p[strlen(p)] = name[0];                /* C, D, X */
  529.         p = buffer;
  530.     }
  531.  
  532.     DEBUG(4, "Munge_filename output: %s\n", p);
  533.     return p;
  534. }
  535.  
  536. /*
  537.  * Uucp work queue scan.  For calling sequences, see sysdep.h.
  538.  */
  539. static DIR    *workdir = (DIR *)NULL;
  540. static struct _xfbuf    xfbuf;
  541. static int    workfile;        /* Do we have one in xfbuf? */
  542. static char    workhost[MAX_HOST+1];
  543. static int    workhlen;
  544. static char    workfirst = 0;
  545.  
  546. void
  547. work_done()
  548. {
  549.     if (workdir)
  550.         closedir(workdir);
  551.     workdir = (DIR *) NULL;
  552.     workfile = 0;
  553.     workfirst = 0;
  554. }
  555.  
  556.  
  557. int
  558. work_scan(host, type)
  559.     char *host;
  560.     char *type;        /* E.g. "C", "X", "LCK" */
  561. {
  562.  
  563.     /* Null argument produces all hostnames */
  564.     if (!host || *host) host="*";
  565.  
  566.     /* If called twice in a row, don't thrash the disk again */
  567.     if (!strcmp(workhost, host) && workfile)
  568.         return 1;
  569.  
  570.     if (workdir) work_done();        /* Clean up prev call */
  571.     
  572.     workfirst = 1;                /* Initialize for work_next */
  573.     workhlen = strlen(host);
  574.     if (workhlen > sizeof (workhost) -1) abort();
  575.     strcpy(workhost, host);
  576.     if (workhlen > 7) workhlen = 7;        /* Unix uucp limit */
  577.  
  578.     strncpy(tempnam, workhost, workhlen);
  579.     strcpy(tempnam+workhlen, "/*.");
  580.     strcat(tempnam+workhlen+    3, type);
  581.  
  582.     workfile = find(tempnam, FALSE, &xfbuf);
  583.     if (!workfile) {
  584.         DEBUG(8, "work_scan readdir null\n", 0);
  585.         work_done();
  586.         return 0;        /* No work */
  587.     }
  588.     return 1;
  589. }
  590.  
  591.  
  592. static int
  593. work_look()
  594. {
  595.     int len;
  596.  
  597.     for (;;) {
  598.         workfile = find(tempnam, TRUE, &xfbuf);
  599.         if (!workfile) {
  600.             DEBUG(8, "work_look readdir null\n", 0);
  601.             work_done();
  602.             return 0;        /* No work */
  603.         }
  604.         DEBUG(8, "work_look readdir %s\n", xfbuf.name);
  605.         /* FIXME, check grade letter! */
  606.         return 1;    /* Found work */
  607.     }
  608.     /* NOTREACHED */
  609. }
  610.  
  611.  
  612. char *
  613. work_next()
  614. {
  615.     /* Space for:       "TYPE.hostnameA1234" */
  616.     static char subhack[6    +MAX_HOST + UFNAMESIZE + SLOP];
  617.  
  618.     if (!workfirst) {
  619.         if (!workfile || !work_look())
  620.             return (char *)NULL;
  621.     }
  622.     workfirst = 0;
  623.  
  624.     /* FIXME, This probably fails for STST and LCK files. */
  625.     p = index(xfbuf.name, '.');
  626.     if (!p) abort();    /* There must be a filename extension */
  627.     *p = '\0';
  628.     sprintf(subhack, "%s.%s%s", p+1, workhost, xfbuf.name);
  629.     return subhack;
  630. }
  631.  
  632. /*
  633.  * Routine to return a string that gives the current date and time, and
  634.  * identifies the current process, if on a multiprocess system.
  635.  *
  636.  * MSDOS multitasking is only a year away, so keep the getpid()...
  637.  */
  638. char *
  639. time_and_pid()
  640. {
  641.     long clock;
  642.     struct tm *tm;
  643.     static int ourpid = 0;
  644.     static char format[] = "%d/%d-%d:%02d:%02d-%d";
  645.     static char outbuf[sizeof(format)];
  646.  
  647.     (void) time(&clock);
  648.     tm = localtime(&clock);
  649.     if (ourpid == 0)
  650.         ourpid = getpid();
  651.     sprintf(outbuf, format,
  652.         tm->tm_mon+1, tm->tm_mday,
  653.         tm->tm_hour, tm->tm_min, tm->tm_sec,
  654.         ourpid);
  655.     return outbuf;
  656. }
  657.